/*
 * Unidata Platform
 * Copyright (c) 2013-2020, UNIDATA LLC, All rights reserved.
 *
 * Commercial License
 * This version of Unidata Platform is licensed commercially and is the appropriate option for the vast majority of use cases.
 *
 * Please see the Unidata Licensing page at: https://unidata-platform.com/license/
 * For clarification or additional options, please contact: info@unidata-platform.com
 * -------
 * Disclaimer:
 * -------
 * THIS SOFTWARE IS DISTRIBUTED "AS-IS" WITHOUT ANY WARRANTIES, CONDITIONS AND
 * REPRESENTATIONS WHETHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION THE
 * IMPLIED WARRANTIES AND CONDITIONS OF MERCHANTABILITY, MERCHANTABLE QUALITY,
 * FITNESS FOR A PARTICULAR PURPOSE, DURABILITY, NON-INFRINGEMENT, PERFORMANCE AND
 * THOSE ARISING BY STATUTE OR FROM CUSTOM OR USAGE OF TRADE OR COURSE OF DEALING.
 */
package org.unidata.mdm.dq.core.migration;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.InputStream;
import java.util.jar.Attributes.Name;
import java.util.jar.JarEntry;
import java.util.jar.JarOutputStream;
import java.util.jar.Manifest;

import org.apache.commons.lang3.ArrayUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.unidata.mdm.core.configuration.CoreConfigurationConstants;
import org.unidata.mdm.core.context.UserLibraryUpsertContext;
import org.unidata.mdm.core.service.UserLibraryService;
import org.unidata.mdm.core.type.libraries.LibraryMimeType;
import org.unidata.mdm.dq.core.configuration.DataQualityCoreConfiguration;
import org.unidata.mdm.dq.core.exception.DataQualityExceptionIds;
import org.unidata.mdm.dq.core.exception.DataQualityRuntimeException;
import org.unidata.mdm.dq.core.service.impl.function.java.JavaCleanseFunctionLibrary;
import org.unidata.mdm.dq.core.util.DQUtils;
import org.unidata.mdm.system.migration.Migrations;
import org.unidata.mdm.system.util.ResourceUtils;

import nl.myndocs.database.migrator.MigrationScript;

/**
 * @author Alexey Tsarapkin
 */
public class DataQualityCoreMigrations {

    private static final Logger LOGGER = LoggerFactory.getLogger("CLEANSE-FUNCTION-INSTALLER");

    private static UserLibraryService userLibraryService;

    private DataQualityCoreMigrations() {
        super();
    }

    public static void init() {
        DataQualityCoreMigrations.userLibraryService = DataQualityCoreConfiguration.getBean(UserLibraryService.class);
    }

    private static final MigrationScript[] INSTALL = {

        Migrations.of("UN-15627-install-dq-schema", "mikhail.mikhailov", ResourceUtils.asString("classpath:/migration/UN-15627-install-dq-schema.sql")),
        Migrations.of("UN-15627-system-cleanse-functions", "mikhail.mikhailov", m -> {

            Manifest mf = new Manifest();
            mf.getMainAttributes().put(Name.MANIFEST_VERSION, "1.2");
            mf.getMainAttributes().put(new Name(CoreConfigurationConstants.CORE_LIBRARIES_VERSION_PROPERTY), "1.0.0");

            byte[] buf = new byte[8096];
            int read = -1;
            ClassLoader ccl = Thread.currentThread().getContextClassLoader();

            ByteArrayOutputStream baos = new ByteArrayOutputStream();
            try (JarOutputStream jos = new JarOutputStream(baos, mf);) {

                for (String name : DQUtils.systemFunctions()) {

                    String path = name.replace('.', '/') + ".class";
                    JarEntry je = new JarEntry(path);
                    jos.putNextEntry(je);

                    InputStream is = ccl.getResourceAsStream(path);
                    while ((read = is.read(buf, 0, buf.length)) != -1) {
                        jos.write(buf, 0, read);
                    }
                }
            } catch (Exception e) {
                throw new DataQualityRuntimeException("Cannot install system cleans functions.", e,
                        DataQualityExceptionIds.EX_DQ_CANNOT_INSTALL_SYSTEM_CLEANSE_FUNCTIONS);
            }

            byte[] payload = baos.toByteArray();
            if (ArrayUtils.isNotEmpty(payload)) {

                ByteArrayInputStream bais = new ByteArrayInputStream(payload);
                UserLibraryUpsertContext ctx = UserLibraryUpsertContext.builder()
                    .description("System cleanse functions.")
                    .filename(JavaCleanseFunctionLibrary.DQ_SYSTEM_CLEANSE_FUNCTIONS_LIBRARY)
                    .version(JavaCleanseFunctionLibrary.DQ_SYSTEM_CLEANSE_FUNCTIONS_VERSION)
                    .mimeType(LibraryMimeType.JAR_FILE.getCode())
                    .input(bais)
                    .force(true)
                    .editable(false)
                    .build();

                userLibraryService.upsert(ctx);

                LOGGER.info("Base system cleanse functions installed.");
            }
        })
    };

    private static final MigrationScript[] UNINSTALL = {
        Migrations.of("alexey.tsarapkin", "UN-15627-uninstall-dq-schema", ResourceUtils.asString("classpath:/migration/UN-15627-uninstall-dq-schema.sql"))
    };

    public static MigrationScript[] install() {
        return INSTALL;
    }

    public static MigrationScript[] uninstall() {
        return UNINSTALL;
    }
}
